package com.mvc.rpc;

import com.mvc.rpc.feign.RemoteProcedureCallFeign;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;

/**
 * Rpc代理工厂类
 * @author JayEinstein
 */
public class RpcProxyFactoryBean<T> implements FactoryBean<T>, ApplicationContextAware, InitializingBean {

    private ApplicationContext applicationContext;

    /**
     * 代理服务接口
     */
    private Class<T> proxyClass;

    /**
     * 直连地址
     */
    private String host;

    /**
     * 服务名称
     */
    private String serviceName;

    private RemoteProcedureCallFeign remoteProcedureCallFeign;

    public RpcProxyFactoryBean() {}

    public RpcProxyFactoryBean(Class<T> proxyClass) {
        this.proxyClass = proxyClass;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public Class<T> getProxyClass() {
        return proxyClass;
    }

    public void setProxyClass(Class<T> proxyClass) {
        this.proxyClass = proxyClass;
    }

    public String getServiceName() {
        return serviceName;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    @Override
    public T getObject() throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(proxyClass);
        RpcServiceProxy interceptor = new RpcServiceProxy(proxyClass);
        interceptor.setHost(host);
        interceptor.setRemoteProcedureCallFeign(remoteProcedureCallFeign);
        enhancer.setCallback(interceptor);
        return (T) enhancer.create();

    }

    @Override
    public Class<?> getObjectType() {
        return proxyClass;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        if (StringUtils.isEmpty(serviceName)) {
            throw new IllegalArgumentException("服务名称不可为空");
        }

        this.remoteProcedureCallFeign = applicationContext.getBean(serviceName, RemoteProcedureCallFeign.class);
    }

}
